home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1993 / Internet Info CD-ROM (Walnut Creek) (1993).iso / networking / ident / servers / aix-identd-1.0.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-10  |  8.3 KB  |  353 lines

  1. /*
  2. This was written for 3.2; it may not work under 3.1, though I'd be 
  3. (relatively) happy to have someone try it.
  4.  
  5. Note that this could probably be more efficient if I could figure out
  6. how to directly search the TCP control blocks.  Unfortunately, I have
  7. no idea where they're stored in the kernel, and I didn't really want to
  8. spend a lot of time figuring it out.  With 20 users logged on and >100
  9. connections, it only takes about .1 second to identify a connection on
  10. this 530.
  11.  
  12. Like authd, pauthd, and pidentd, aixident is meant to be started from
  13. inetd:
  14.  
  15. ident   stream  tcp     nowait  root    /usr/local/etc/aixident in.identd -l
  16.  
  17. The name is pronounced like "accident", because that's what I believe
  18. RFC931 is.  Use at your own risk.
  19. */
  20.  
  21. /*
  22. **  aixident -- AIX identification daemon
  23. **  version 1.0
  24. **
  25. **  Copyright 1992 by Charles M. Hannum.
  26. **
  27. **  Permission is granted to copy, modify, and use this program in any way,
  28. **  so long as the above copyright notice, this permission notice, and the
  29. **  warranty disclaimer below remain on all copies, and are unaltered.
  30. **
  31. **  aixident is distributed in the hope that it will be useful, but WITHOUT
  32. **  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  33. **  FITNESS FOR A PARTICULAR PURPOSE.
  34. */
  35.  
  36. /*
  37. **  Usage:
  38. **
  39. **    aixident [-l] [-V] [-v] [-d] [kmem_file]
  40. **
  41. **  Where:
  42. **
  43. **    -l  log via syslog
  44. **
  45. **    -V  print version number and exit
  46. **
  47. **    -v  verbose (currently useless)
  48. **
  49. **    -d  enable debugging; lists connections in a lsof-like manner
  50. **
  51. **    kmem_file  file to read kernel memory from
  52. */
  53.  
  54. char version[] = "aixident, version 1.0";
  55.  
  56. #include <sys/types.h>
  57.  
  58. #include <stdlib.h>
  59. #include <errno.h>
  60. #include <pwd.h>
  61. #include <stdio.h>
  62. #include <syslog.h>
  63.  
  64. #include <sys/domain.h>
  65. #include <sys/protosw.h>
  66. #include <sys/socket.h>
  67. #include <sys/socketvar.h>
  68. #include <sys/vfs.h>
  69. #include <net/route.h>
  70. #include <netinet/in.h>
  71. #include <netinet/in_pcb.h>
  72. #include <arpa/inet.h>
  73.  
  74. #define _KERNEL 1
  75. #include <sys/file.h>
  76. #undef  _KERNEL
  77. #include <procinfo.h>
  78.  
  79. int kmem;
  80.  
  81. int kread ();
  82. char *printuid ();
  83. void printaddr ();
  84.  
  85. int syslog_flag = 0,
  86.     verbose_flag = 0,
  87.     debug_flag = 0;
  88.  
  89. #define ERROR(v,m) \
  90.   do {                                    \
  91.     printf ("%d, %d: ERROR: %s\r\n", local_port, foreign_port, m);    \
  92.     exit (v);                                \
  93.   } while (0)
  94.  
  95. #define UNKNOWN_ERROR() ERROR (1, "UNKNOWN-ERROR");
  96.  
  97. int
  98. main (argc, argv)
  99.   int argc;
  100.   char **argv;
  101. {
  102.   char *path_kmem = "/dev/kmem";
  103.   struct sockaddr_in foreign, local;
  104.   int foreign_len, local_len;
  105.   int foreign_port = 0, local_port = 0;
  106.   int max_procs = 64,
  107.       num_procs, fd;
  108.   struct procinfo *procinfo;
  109.   struct user user;
  110.   struct file *filep, file;
  111.   struct socket *socketp, socket;
  112.   struct protosw *protoswp, protosw;
  113.   struct domain *domainp, domain;
  114.   struct inpcb *inpcbp, inpcb;
  115.   struct passwd *passwd;
  116.  
  117.   for (--argc; argc && **++argv == '-'; argc--)
  118.     while (*(++*argv))
  119.       switch (**argv) {
  120.         case 'l':
  121.       syslog_flag = 1;
  122.       break;
  123.     case 'V':
  124.       puts (version);
  125.       exit (0);
  126.       break;
  127.     case 'v':
  128.       verbose_flag = 1;
  129.       break;
  130.     case 'd':
  131.       debug_flag = 1;
  132.       break;
  133.       }
  134.  
  135.   if (argc) {
  136.     path_kmem = *(argv++);
  137.     --argc;
  138.   }
  139.  
  140.   foreign_len = sizeof (foreign);
  141.   if (getpeername (0, &foreign, &foreign_len) == -1) {
  142.     perror ("getpeername");
  143.     exit (1);
  144.   }
  145.  
  146.   local_len = sizeof (local);
  147.   if (getsockname (0, &local, &local_len) == -1) {
  148.     perror ("getsockname");
  149.     exit (1);
  150.   }
  151.  
  152.   if (syslog_flag) {
  153.     (void) openlog ("identd", LOG_PID, LOG_DAEMON);
  154.     (void) syslog (LOG_NOTICE, "Connection from %s",
  155.            inet_ntoa (foreign.sin_addr.s_addr));
  156.   }
  157.  
  158.   if (scanf ("%d , %d", &local_port, &foreign_port) != 2 ||
  159.       local_port < 1 || local_port > 65535 || foreign_port < 1 ||
  160.       foreign_port > 65535) {
  161.     if (syslog_flag)
  162.       (void) syslog (LOG_INFO, "invalid port(s): %d, %d", local_port,
  163.              foreign_port);
  164.     ERROR (0, "INVALID-PORT");
  165.   }
  166.  
  167.   if ((kmem = open (path_kmem, O_RDONLY)) == -1) {
  168.     if (syslog_flag)
  169.       (void) syslog (LOG_ERR, "error opening /dev/kmem: %s", strerror (errno));
  170.     UNKNOWN_ERROR ();
  171.   }
  172.  
  173.   while ((procinfo = (struct procinfo *)
  174.              malloc ((size_t) (max_procs * sizeof (*procinfo)))) &&
  175.          (num_procs = getproc (procinfo, max_procs,
  176.                    sizeof (*procinfo))) == -1 &&
  177.      errno == ENOSPC) {
  178.     max_procs <<= 1;
  179.     free (procinfo);
  180.   }
  181.  
  182.   if (! procinfo) {
  183.     if (syslog_flag)
  184.       (void) syslog (LOG_ERR, "out of memory allocating %ld procinfo structs\n",
  185.              max_procs);
  186.     UNKNOWN_ERROR ();
  187.   }
  188.  
  189.   for (; num_procs; num_procs--, procinfo++) {
  190.  
  191.     if (procinfo->pi_stat == 0 || procinfo->pi_stat == SZOMB)
  192.       continue;
  193.  
  194.     if (getuser (procinfo, sizeof (*procinfo), &user, sizeof (user)))
  195.       continue;
  196.  
  197.     for (fd = 0; fd < user.u_maxofile; fd++) {
  198.  
  199.       if (! (filep = user.u_ufd[fd].fp))
  200.     continue;
  201.  
  202.       if (kread ((off_t) filep, (char *) &file, sizeof (file))) {
  203.     if (syslog_flag)
  204.           (void) syslog (LOG_ERR, "can't read file struct from %#x",
  205.                  (unsigned) filep);
  206.     UNKNOWN_ERROR ();
  207.       }
  208.  
  209.       if (file.f_type != DTYPE_SOCKET)
  210.     continue;
  211.  
  212.       if (! (socketp = (struct socket *) file.f_data))
  213.     continue;
  214.  
  215.       if (kread ((off_t) socketp, (char *) &socket, sizeof (socket))) {
  216.     if (syslog_flag)
  217.           (void) syslog (LOG_ERR, "can't read socket struct from %#x",
  218.              (unsigned) socketp);
  219.     UNKNOWN_ERROR ();
  220.       }
  221.  
  222.       if (! (protoswp = socket.so_proto))
  223.     continue;
  224.  
  225.       if (kread ((off_t) protoswp, (char *) &protosw, sizeof (protosw))) {
  226.     if (syslog_flag)
  227.       (void) syslog (LOG_ERR, "can't read protosw struct from %#x",
  228.              (unsigned) protoswp);
  229.     UNKNOWN_ERROR ();
  230.       }
  231.  
  232.       if (protosw.pr_protocol != IPPROTO_TCP)
  233.     continue;
  234.  
  235.       if (! (domainp = protosw.pr_domain))
  236.     continue;
  237.  
  238.       if (kread ((off_t) domainp, (char *) &domain, sizeof (domain))) {
  239.     if (syslog_flag)
  240.       (void) syslog (LOG_ERR, "can't read domain struct from %#x",
  241.              (unsigned) domainp);
  242.     UNKNOWN_ERROR ();
  243.       }
  244.  
  245.       if (domain.dom_family != AF_INET)
  246.     continue;
  247.  
  248.       if (! (inpcbp = (struct inpcb *) socket.so_pcb))
  249.     continue;
  250.  
  251.       if (kread ((off_t) inpcbp, (char *) &inpcb, sizeof (inpcb))) {
  252.     if (syslog_flag)
  253.       (void) syslog (LOG_ERR, "can't read inpcb struct from %#x",
  254.              (unsigned) inpcbp);
  255.     UNKNOWN_ERROR ();
  256.       }
  257.  
  258.       if (socketp != inpcb.inp_socket)
  259.     continue;
  260.  
  261.       if (inpcb.inp_faddr.s_addr != foreign.sin_addr.s_addr ||
  262.       inpcb.inp_fport != foreign_port ||
  263.       inpcb.inp_laddr.s_addr != local.sin_addr.s_addr ||
  264.       inpcb.inp_lport != local_port)
  265.     continue;
  266.  
  267.       if (! (passwd = getpwuid (procinfo->pi_uid))) {
  268.     if (syslog_flag)
  269.       (void) syslog (LOG_WARNING, "could not map uid to name: %d",
  270.              procinfo->pi_uid);
  271.     UNKNOWN_ERROR ();
  272.       }
  273.  
  274.       if (!debug_flag) {
  275.         if (syslog_flag)
  276.       (void) syslog (LOG_NOTICE, "identified: %d, %d, %s", local_port,
  277.                  foreign_port, passwd->pw_name);
  278.         printf ("%d, %d: USERID: UNIX: %s\r\n", local_port, foreign_port,
  279.             passwd->pw_name);
  280.         exit (0);
  281.       } else {
  282.         printf ("%-9.9s%6d %8s %4d%c %4.4s 0x%08x %8s %7.7s ",
  283.                 user.u_comm, procinfo->pi_pid, printuid (procinfo->pi_uid),
  284.                 fd, ' ', "inet", inpcb.inp_ppcb ?
  285.                                    (int) inpcb.inp_ppcb : (int) socket.so_pcb,
  286.                 "", "TCP");
  287.  
  288.         printaddr (&inpcb.inp_laddr, inpcb.inp_lport);
  289.         if (inpcb.inp_faddr.s_addr != INADDR_ANY || inpcb.inp_fport) {
  290.           printf ("->");
  291.           printaddr (&inpcb.inp_faddr, inpcb.inp_fport);
  292.         }
  293.  
  294.         printf ("\n");
  295.       }
  296.     }
  297.   }
  298.  
  299.   if (syslog_flag)
  300.     (void) syslog (LOG_DEBUG, "not found: %d, %d", local_port, foreign_port);
  301.   ERROR (0, "NO-USER");
  302. }
  303.  
  304. int
  305. kread (addr, buf, len)
  306.   off_t addr;
  307.   char *buf;
  308.   int len;
  309. {
  310.   int br;
  311.  
  312.   if (lseek (kmem, addr, L_SET) == (off_t) -1)
  313.     return (-1);
  314.  
  315.   br = read(kmem, buf, len);
  316.  
  317.   return ((br == len) ? 0 : 1);
  318. }
  319.  
  320. char *
  321. printuid (uid)
  322.   uid_t uid;
  323. {
  324.   static int used = 0;
  325.   static uid_t last_uid;
  326.   struct passwd *passwd;
  327.   static char user[9];
  328.  
  329.   if (!used || uid != last_uid) {
  330.     used = 1;
  331.     last_uid = uid;
  332.  
  333.     if (passwd = getpwuid (uid))
  334.       (void) strcpy (user, passwd->pw_name);
  335.     else
  336.       (void) sprintf (user, "%d", uid);
  337.   }
  338.  
  339.   return (user);
  340. }
  341.  
  342. void
  343. printaddr (in_addr, port)
  344.   struct in_addr *in_addr;
  345.   u_short port;
  346. {
  347.   if (in_addr->s_addr == INADDR_ANY)
  348.     printf ("*:%d", port);
  349.   else
  350.     printf ("%s:%d", inet_ntoa (in_addr->s_addr), port);
  351. }
  352.  
  353.